{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "## 使用 Scikit-Learning 构建决策树\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/edgar/miniconda3/envs/tiny-mall/lib/python3.8/site-packages/sklearn/utils/deprecation.py:143: FutureWarning: The sklearn.datasets.california_housing module is  deprecated in version 0.22 and will be removed in version 0.24. The corresponding classes / functions should instead be imported from sklearn.datasets. Anything that cannot be imported from sklearn.datasets is now part of the private API.\n",
      "  warnings.warn(message, FutureWarning)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      ".. _california_housing_dataset:\n",
      "\n",
      "California Housing dataset\n",
      "--------------------------\n",
      "\n",
      "**Data Set Characteristics:**\n",
      "\n",
      "    :Number of Instances: 20640\n",
      "\n",
      "    :Number of Attributes: 8 numeric, predictive attributes and the target\n",
      "\n",
      "    :Attribute Information:\n",
      "        - MedInc        median income in block\n",
      "        - HouseAge      median house age in block\n",
      "        - AveRooms      average number of rooms\n",
      "        - AveBedrms     average number of bedrooms\n",
      "        - Population    block population\n",
      "        - AveOccup      average house occupancy\n",
      "        - Latitude      house block latitude\n",
      "        - Longitude     house block longitude\n",
      "\n",
      "    :Missing Attribute Values: None\n",
      "\n",
      "This dataset was obtained from the StatLib repository.\n",
      "http://lib.stat.cmu.edu/datasets/\n",
      "\n",
      "The target variable is the median house value for California districts.\n",
      "\n",
      "This dataset was derived from the 1990 U.S. census, using one row per census\n",
      "block group. A block group is the smallest geographical unit for which the U.S.\n",
      "Census Bureau publishes sample data (a block group typically has a population\n",
      "of 600 to 3,000 people).\n",
      "\n",
      "It can be downloaded/loaded using the\n",
      ":func:`sklearn.datasets.fetch_california_housing` function.\n",
      "\n",
      ".. topic:: References\n",
      "\n",
      "    - Pace, R. Kelley and Ronald Barry, Sparse Spatial Autoregressions,\n",
      "      Statistics and Probability Letters, 33 (1997) 291-297\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn.datasets.california_housing import fetch_california_housing\n",
    "housing_data = fetch_california_housing()\n",
    "print(housing_data.DESCR)\n",
    "# 来源 http://lib.stat.cmu.edu/datasets/\n",
    "#  Attribute Information:\n",
    "#          - MedInc        median income in block\n",
    "#          - HouseAge      median house age in block\n",
    "#          - AveRooms      average number of rooms\n",
    "#          - AveBedrms     average number of bedrooms\n",
    "#          - Population    block population\n",
    "#          - AveOccup      average house occupancy\n",
    "#          - Latitude      house block latitude\n",
    "#          - Longitude     house block longitude"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "data": {
      "text/plain": "(20640, 8)"
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "housing_data.data.shape # 数据结构"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [
    {
     "data": {
      "text/plain": "array([ 8.30140000e+00,  2.10000000e+01,  6.23813708e+00,  9.71880492e-01,\n        2.40100000e+03,  2.10984183e+00,  3.78600000e+01, -1.22220000e+02])"
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "housing_data.data[0] # 查看数据精度"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "data": {
      "text/plain": "DecisionTreeRegressor(max_depth=2)"
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn import tree\n",
    "dtr = tree.DecisionTreeRegressor(max_depth=2) # 使用参数， 实例化一个算法\n",
    "dtr.fit(housing_data.data[:,[6,7]], housing_data.target) # 使用经纬度，\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [],
   "source": [
    "# 要可视化显示， 需要安装 graphviz\n",
    "dot_data = tree.export_graphviz(\n",
    "  dtr,\n",
    "  out_file=None,\n",
    "  feature_names=housing_data.feature_names[6:8],\n",
    "  filled=True,\n",
    "  impurity=False,\n",
    "  rounded=True)\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [
    {
     "ename": "InvocationException",
     "evalue": "GraphViz's executables not found",
     "output_type": "error",
     "traceback": [
      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[0;31mInvocationException\u001B[0m                       Traceback (most recent call last)",
      "\u001B[0;32m<ipython-input-14-4998f2f2e972>\u001B[0m in \u001B[0;36m<module>\u001B[0;34m\u001B[0m\n\u001B[1;32m      4\u001B[0m \u001B[0mgraph\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mget_nodes\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m[\u001B[0m\u001B[0;36m7\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mset_fillcolor\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m'#fff2dd'\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m      5\u001B[0m \u001B[0;32mfrom\u001B[0m \u001B[0mIPython\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mdisplay\u001B[0m \u001B[0;32mimport\u001B[0m \u001B[0mImage\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m----> 6\u001B[0;31m \u001B[0mImage\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mgraph\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mcreate_png\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m      7\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n",
      "\u001B[0;32m~/miniconda3/envs/tiny-mall/lib/python3.8/site-packages/pydotplus/graphviz.py\u001B[0m in \u001B[0;36m<lambda>\u001B[0;34m(f, prog)\u001B[0m\n\u001B[1;32m   1795\u001B[0m             self.__setattr__(\n\u001B[1;32m   1796\u001B[0m                 \u001B[0;34m'create_'\u001B[0m \u001B[0;34m+\u001B[0m \u001B[0mfrmt\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m-> 1797\u001B[0;31m                 \u001B[0;32mlambda\u001B[0m \u001B[0mf\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mfrmt\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mprog\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mprog\u001B[0m\u001B[0;34m:\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mcreate\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mformat\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mf\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mprog\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mprog\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m   1798\u001B[0m             )\n\u001B[1;32m   1799\u001B[0m             \u001B[0mf\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m__dict__\u001B[0m\u001B[0;34m[\u001B[0m\u001B[0;34m'create_'\u001B[0m \u001B[0;34m+\u001B[0m \u001B[0mfrmt\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n",
      "\u001B[0;32m~/miniconda3/envs/tiny-mall/lib/python3.8/site-packages/pydotplus/graphviz.py\u001B[0m in \u001B[0;36mcreate\u001B[0;34m(self, prog, format)\u001B[0m\n\u001B[1;32m   1957\u001B[0m             \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mprogs\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mfind_graphviz\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m   1958\u001B[0m             \u001B[0;32mif\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mprogs\u001B[0m \u001B[0;32mis\u001B[0m \u001B[0;32mNone\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m-> 1959\u001B[0;31m                 raise InvocationException(\n\u001B[0m\u001B[1;32m   1960\u001B[0m                     'GraphViz\\'s executables not found')\n\u001B[1;32m   1961\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n",
      "\u001B[0;31mInvocationException\u001B[0m: GraphViz's executables not found"
     ]
    }
   ],
   "source": [
    "# pip install pydotplus ( pydotplus-2.0.2)\n",
    "import pydotplus\n",
    "graph = pydotplus.graph_from_dot_data(dot_data)\n",
    "graph.get_nodes()[7].set_fillcolor('#fff2dd')\n",
    "from IPython.display import Image\n",
    "Image(graph.create_png())"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "ename": "InvocationException",
     "evalue": "GraphViz's executables not found",
     "output_type": "error",
     "traceback": [
      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[0;31mInvocationException\u001B[0m                       Traceback (most recent call last)",
      "\u001B[0;32m<ipython-input-15-da1af1dc5d0f>\u001B[0m in \u001B[0;36m<module>\u001B[0;34m\u001B[0m\n\u001B[0;32m----> 1\u001B[0;31m \u001B[0mgraph\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mwrite_png\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m'dtr_white.png'\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m      2\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n",
      "\u001B[0;32m~/miniconda3/envs/tiny-mall/lib/python3.8/site-packages/pydotplus/graphviz.py\u001B[0m in \u001B[0;36m<lambda>\u001B[0;34m(path, f, prog)\u001B[0m\n\u001B[1;32m   1808\u001B[0m                 \u001B[0;32mlambda\u001B[0m \u001B[0mpath\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m   1809\u001B[0m                 \u001B[0mf\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mfrmt\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m-> 1810\u001B[0;31m                 \u001B[0mprog\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mprog\u001B[0m\u001B[0;34m:\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mwrite\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mpath\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mformat\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mf\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mprog\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mprog\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m   1811\u001B[0m             )\n\u001B[1;32m   1812\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n",
      "\u001B[0;32m~/miniconda3/envs/tiny-mall/lib/python3.8/site-packages/pydotplus/graphviz.py\u001B[0m in \u001B[0;36mwrite\u001B[0;34m(self, path, prog, format)\u001B[0m\n\u001B[1;32m   1916\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m   1917\u001B[0m             \u001B[0;32melse\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m-> 1918\u001B[0;31m                 \u001B[0mfobj\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mwrite\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mcreate\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mprog\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mformat\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m   1919\u001B[0m         \u001B[0;32mfinally\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m   1920\u001B[0m             \u001B[0;32mif\u001B[0m \u001B[0mclose\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n",
      "\u001B[0;32m~/miniconda3/envs/tiny-mall/lib/python3.8/site-packages/pydotplus/graphviz.py\u001B[0m in \u001B[0;36mcreate\u001B[0;34m(self, prog, format)\u001B[0m\n\u001B[1;32m   1957\u001B[0m             \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mprogs\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mfind_graphviz\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m   1958\u001B[0m             \u001B[0;32mif\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mprogs\u001B[0m \u001B[0;32mis\u001B[0m \u001B[0;32mNone\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m-> 1959\u001B[0;31m                 raise InvocationException(\n\u001B[0m\u001B[1;32m   1960\u001B[0m                     'GraphViz\\'s executables not found')\n\u001B[1;32m   1961\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n",
      "\u001B[0;31mInvocationException\u001B[0m: GraphViz's executables not found"
     ]
    }
   ],
   "source": [
    "graph.write_png('dtr_white.png')\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 将数据切分成 训练集和测试集"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "data": {
      "text/plain": "0.6310922690494536"
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "data_train, data_test, target_train, target_test = \\\n",
    "train_test_split(housing_data.data, housing_data.target, test_size=0.1, random_state=42)\n",
    "dtr = tree.DecisionTreeRegressor(random_state=42) # 使用固定的随机种子\n",
    "dtr.fit(data_train, target_train) # 使用经纬度，\n",
    "dtr.score(data_test, target_test)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [],
   "source": [
    "from sklearn.ensemble import RandomForestRegressor"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'GridSearchCV' object has no attribute 'grid_scores_'",
     "output_type": "error",
     "traceback": [
      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[0;31mAttributeError\u001B[0m                            Traceback (most recent call last)",
      "\u001B[0;32m<ipython-input-20-2a9cc6ca1f9d>\u001B[0m in \u001B[0;36m<module>\u001B[0;34m\u001B[0m\n\u001B[1;32m      4\u001B[0m \u001B[0mgrid\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mGridSearchCV\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mRandomForestRegressor\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mparam_grid\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mtree_param_grid\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mcv\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;36m5\u001B[0m\u001B[0;34m)\u001B[0m \u001B[0;31m# 交叉验证\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m      5\u001B[0m \u001B[0mgrid\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mfit\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mdata_train\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mtarget_train\u001B[0m\u001B[0;34m)\u001B[0m \u001B[0;31m# 使用经纬度，\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m----> 6\u001B[0;31m \u001B[0mgrid\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mgrid_scores_\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0mgrid\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mbest_params_\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mgrid\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mbest_score_\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m      7\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n",
      "\u001B[0;31mAttributeError\u001B[0m: 'GridSearchCV' object has no attribute 'grid_scores_'"
     ]
    }
   ],
   "source": [
    "# grid search  参数的组合和选择\n",
    "from sklearn.model_selection import GridSearchCV\n",
    "tree_param_grid = { 'min_samples_split':list((3,6,9)), 'n_estimators': list((10,50,100))}\n",
    "grid = GridSearchCV(RandomForestRegressor(), param_grid=tree_param_grid, cv=5) # 交叉验证\n",
    "grid.fit(data_train, target_train) # 使用经纬度，\n",
    "grid.best_params_, grid.best_score_\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}